﻿#include "TetrisGame.h"
#include "Define.h"
#include "TetrisBoard.h"
#include "TetrisBlock.h"

TetrisGame::TetrisGame(void)
	: speed_(200),
	gameover_(false),
	pBoard_(NULL),
	pBlock_(NULL)//,
	//pos_(4,0),
{
	Init();
}


TetrisGame::~TetrisGame(void)
{
	Release();
}

/**
@brief 테트리스 초기화
@date 2013/01/14
@author 임진영(deviak@deviak.com)
@return void
*/
void TetrisGame::Init()
{
	if(!pBoard_)
		pBoard_ = new TetrisBoard(this);
	pBoard_->Init();

	if(!pBlock_)
		pBlock_ = new TetrisBlock(this);
	pBlock_->Init();

	score_ = 0;
	SetCursorType(CURSOR_NO); 

	MakeBlock();
}


/**
@brief 랜덤으로 테트리스 Block을 생성한다
@date 2013/01/14
@author 임진영(deviak@deviak.com)
@return bool
*/
bool TetrisGame::MakeBlock()
{
	pBlock_->CreateBlock();
	return pBoard_->CheckCreateBlock(pBlock_->Block());
}


/**
@brief Block을 회전시킨다
@date 2013/01/14
@author 임진영(deviak@deviak.com)
@return bool
*/
bool TetrisGame::TurnBlock()
{
	return pBlock_->TurnBlock();
}

/**
@brief 테트리스 Block을 삭제한다
@remarks Block이 충돌이 났는지 검사하고 충돌이 나지 않으면 움직이고 그렇지 않으면 board를 stage로 옮긴 후 새로운 Block을 생성한다.
@date 2013/01/14
@author 임진영(deviak@deviak.com)
@return void
*/
void TetrisGame::DeleteBlocks()
{
	POSITION pos(pBlock_->Pos().x_, pBlock_->Pos().y_+1);
	if(!CheckOver(pos)) {		///< 충돌이 났는지 검사한다
		pBlock_->MoveBlock(pos);			///< 충돌이 나지 않으면 블록을 움직인다
	}else{
		pBoard_->BlockOn();								///< board_를 stage_로 옮기며 line을 검사한다
		MakeBlock();									///< 새로운 블록을 생선한다
	}
}

/**
@brief Block이 충돌이 났는지 검사한다
@date 2013/01/14
@author 임진영(deviak@deviak.com)
@param const POSITION & p
@return bool
*/
bool TetrisGame::CheckOver(const POSITION &p)
{
	return pBoard_->CheckOver(p, pBlock_->Block());
}

/**
@brief 게임 타이틀 화면
@date 2013/01/14
@author 임진영(deviak@deviak.com)
@return void
*/
void TetrisGame::Title()
{
	system("cls");

	cout<<"================================================================================"<<endl;

	cout << "                               T E T R I S                                   " << endl << endl << endl;
	cout << "                          Please input any key                               " << endl << endl << endl;
	
	cout<<"================================================================================"<<endl;
	WaitAnyKey();
}

/**
@brief 게임 종료 화면
@date 2013/01/14
@author 임진영(deviak@deviak.com)
@return void
*/
void TetrisGame::GameOver()
{
	system("cls");

	cout<<"================================================================================"<<endl;

	cout << "                               G A M E O V E R                               " << endl << endl << endl;
	cout << "                             Please input any key                            " << endl << endl << endl;
	
	cout<<"================================================================================"<<endl;
	WaitAnyKey();
}


/**
@brief 테트리스 정보 업데이트
@date 2013/01/14
@author 임진영(deviak@deviak.com)
@return void
*/
void TetrisGame::Update()
{
	Input();				///< Input 처리
	DeleteBlocks();			///< DeleteBlocks
}

/**
@brief 입력 처리
@remarks 입력을 받아 블록을 움직이거나 회전 시킨다
@date 2013/01/14
@author 임진영(deviak@deviak.com)
@return void
*/
void TetrisGame::Input()
{
	if(!_kbhit()) {
		return;
	}

	int ch;
	ch = _getch();
	if (ch == 0xE0 || ch == 0) 
	{
		ch = _getch();
		POSITION pos(pBlock_->Pos());

		switch(ch)
		{
		case LEFT:
			if(!CheckOver(POSITION(pos.x_-1, pos.y_)))
				pBlock_->MoveBlock(POSITION(pos.x_-1, pos.y_));
			break;
		case RIGHT:
			if(!CheckOver(POSITION(pos.x_+1, pos.y_)))
				pBlock_->MoveBlock(POSITION(pos.x_+1, pos.y_));
			break;
		case DOWN:
			if(!CheckOver(POSITION(pos.x_, pos.y_+1)))
				pBlock_->MoveBlock(POSITION(pos.x_, pos.y_+1));
			break;
		case UP:
			TurnBlock();
			break;
		}
	}
	else
	{
		switch(tolower(ch))
		{
		case 27:
			SetCursorType(CURSOR_NO);
			exit(0);
		case 'p':
			WaitAnyKey();
			break;
		}
	}
}

/**
@brief 테트리스 출력
@date 2013/01/14
@author 임진영(deviak@deviak.com)
@return void
*/
void TetrisGame::Render()
{
	system("cls");
	DrawUI();
	pBoard_->Render();
	pBlock_->Render();
}

/**
@brief 메모리 해제
@date 2013/01/14
@author 임진영(deviak@deviak.com)
@return void
*/
void TetrisGame::Release()
{
	SAFE_DELETE(pBoard_);
}

/**
@brief UI를 출력한다
@date 2013/01/14
@author 임진영(deviak@deviak.com)
@return void
*/
void TetrisGame::DrawUI()
{
	MoveCursor(POSITION(20, 5));
	cout << "현재 스코어 : " << score_ << std::flush;
}

/**
@brief Score를 증가시킨다
@date 2013/01/24
@author 임진영(deviak@deviak.com)
@return void
*/
void TetrisGame::IncreaseScore()
{
	score_++;
}